/**
 *	@file	pgmap_mk.c
 *	@brief	ポケギア　マーカー関連
 *	@author	Miyuki Iwasawa
 *	@date	07.08.03
 */

#include "common.h"
#include "system/procsys.h"
#include "system/arc_util.h"
#include "system/arc_tool.h"
#include "system/brightness.h"
#include "system/bmp_list.h"
#include "system/bmp_menu.h"
#include "system/pm_str.h"
#include "system/msgdata.h"
#include "system/fontproc.h"
#include "system/snd_tool.h"
#include "system/clact_util.h"
#include "system/clact_tool.h"
#include "system/render_oam.h"
#include "system/wipe.h"
#include "system/buflen.h"
#include "gflib/touchpanel.h"
#include "field/field_matrix.h"
#include "field/field_place_name.h"
#include "application/app_tool.h"
#include "application/pokegear.h"
#include "msgdata/msg.naix"
#include "fielddata/maptable/zone_id.h"

#include "../pgear_sys.h"
#include "../pgear_frm.h"
#include "../pgear_act.h"
#include "savedata/marker_util.h"
#include "pgmap_sys.h"
#include "pgmap_bg.h"
#include "pgmap_sub.h"
#include "pgmap_key.h"

#define __PGMAP_MK_H_GLOBAL
#include "pgmap_mk.h"

/*
 *	@brief	マーカーリストワークをクリア
 */
static void PGMapWk_ListWkClear(MARKER_LIST* dat)
{
	dat->valid = 0;
	dat->myid = dat->prev = dat->next = 0xFF;

	MarkerDataWk_Clear(&dat->mark);
}

/**
 *	@brief	マーカーリストの空きワークを取得
 */
static u8 PGMapWk_GetEmptyWork(PGMAP_SYS_WORK* wk)
{
	u8 i;

	for(i = 0;i < MARKER_STOCK_MAX;i++){
		if(wk->mk_list[i].valid == 0){
			return i;
		}
	}
	return 0xFF;
}

/**
 *	@brief	セーブされたマーカーデータを取得
 */
void PGMapMk_GetSaveData(PGMAP_SYS_WORK* wk)
{
	u8 i,idx;

	MARKER_BLOCK* pb;
	MARKER_LIST* pl;

	//ブロックデータポインタ取得
	pb = PGearSv_GetMarkerBlockP(wk->sys->pg_save);

	//スタートとエンドを初期化
	wk->mk_sid = wk->mk_eid = 0xFF;

	//全配列を初期化
	for(i = 0;i < MARKER_STOCK_MAX;i++){
		PGMapWk_ListWkClear(&(wk->mk_list[i]));
	}
	//有効データをリストに取得
	idx = 0;
	for(i = 0;i < MARKER_STOCK_MAX;i++){
		if(!MarkerBlock_IsMarkDataEnable(pb,i)){
			break;
		}
		pl = &(wk->mk_list[idx]);
		MarkerBlock_GetWorkFromIdx(pb,&(pl->mark),i);
		pl->myid = idx;
		pl->valid = TRUE;

		//リストの初期化
		if(wk->mk_sid == 0xFF){
			wk->mk_sid = pl->myid;
			wk->mk_eid = pl->myid;
			pl->prev = 0xFF;
		}else{
			pl->prev = wk->mk_eid;
			wk->mk_list[wk->mk_eid].next = pl->myid;
			wk->mk_eid = pl->myid;
		}
		idx++;
	}
	wk->mk_initNum = idx;	//初期登録数を覚えておく
}

/*
 *	@brief	編集されたマーカーデータをセーブデータに書き戻し
 */
void PGMapMk_SetSaveData(PGMAP_SYS_WORK* wk)
{
	u8 i,next_id,idx;
	MARKER_BLOCK* pb;
	MARKER_LIST* pl;

	//ブロックデータポインタ取得
	pb = PGearSv_GetMarkerBlockP(wk->sys->pg_save);

	idx = 0;
	//一番上から上書きでデータを詰める
	for(i = wk->mk_sid;(i != 0xFF);i = next_id){
		pl = &(wk->mk_list[i]);
		MarkerBlock_SetWorkFromIdx(pb,&(pl->mark),idx++,TRUE);
		next_id = pl->next;
	}

	//空き領域をクリア
	for(i = idx;i < wk->mk_initNum;i++){
		MarkerBlock_DataClearFromIdx(pb,i);
	}
}

/*
 *	@brief	有効リスト内に指定のゾーンIDをキーに持つデータがあるか？
 */
MARKER_LIST*	PGMapMk_SearchListFromZone(PGMAP_SYS_WORK* wk,int zone)
{
	u8 i,next_id;
	MARKER_LIST* pl;

	if(zone <= ZONE_ID_EVERYWHERE){
		return NULL;
	}
	for(i = wk->mk_sid;(i != 0xFF);i = next_id){
		pl = &(wk->mk_list[i]);
		if(pl->mark.zone == zone){
			return pl;
		}
		next_id = pl->next;
	}
	return NULL;
}

/*
 *	@brief	指定ゾーンのマーキングデータを有効リストに登録
 */
MARKER_LIST* PGMapMk_EntryZoneData(PGMAP_SYS_WORK* wk,int zone)
{
	MARKER_LIST* pl;
	u8 idx;

	pl = PGMapMk_SearchListFromZone(wk,zone);
	if(pl != NULL){
		return pl;	//既に有効リストに存在する
	}
	//空きワークを探す
	idx = PGMapWk_GetEmptyWork(wk);
	if(idx == 0xFF){
		IWASAWA_PRINT("\nERROR:マーカーワークに空きがありません\n");
		GF_ASSERT(0);
		return NULL;	//空きがない(が、空きがなくなることはないはず)
	}
	pl = &(wk->mk_list[idx]);
	pl->myid = idx;	///自分のナンバーを覚えておく
	pl->valid = TRUE;

	pl->mark.zone = zone;

	if(wk->mk_sid == 0xFF){
		//リストの最初に追加
		wk->mk_sid = wk->mk_eid = idx;
		pl->prev = 0xFF;
	}else{
		//リストの一番最後に追加
		wk->mk_list[wk->mk_eid].next = idx;
		pl->prev = wk->mk_eid;
		wk->mk_eid = idx;	//自分が最後
	}
	return pl;
}

/**
 *	@brief	指定ゾーンのマーカーデータを有効リストから削除
 */
int PGMapMk_DeleteZoneData(PGMAP_SYS_WORK* wk,MARKER_LIST* pl)
{
	u8 idx;

	if(pl == NULL){
		return FALSE;	//既に有効リストに存在しない
	}
	//リストチェーンから外す
	if(pl->myid == wk->mk_sid){
		if(pl->next == 0xFF){
			//リストが0個になった
			wk->mk_sid = wk->mk_eid = 0xFF;
		}else{
			//自分の次がリストの最初になる
			wk->mk_sid = wk->mk_list[pl->next].myid;
			wk->mk_list[pl->next].prev = 0xFF;
		}
	}else if(pl->myid == wk->mk_eid){
		//自分の前がリストの最後になる
		wk->mk_list[pl->prev].next = 0xFF;
		wk->mk_eid = wk->mk_list[pl->prev].myid;
	}else{
		wk->mk_list[pl->prev].next = pl->next;
		wk->mk_list[pl->next].prev = pl->prev;
	}
	//自分自身をクリア
	PGMapWk_ListWkClear(pl);
	return TRUE;
}

/**
 *	@brief	指定ゾーンのマーカーデータにアイコンパラメータを追加
 */
int PGMapMk_AddIconParam(MARKER_LIST* pl,u8 idx,u8 param)
{
	if(pl == NULL){
		return FALSE;
	}
	pl->mark.icon[idx] = param;
	return TRUE;
}

/*
 *	@brief	指定ゾーンのマーカーデータからアイコンパラメータを削除
 *
 *	@retval	TRUE:有効なパラメータが残っている
 *	@retval FALSE:有効なパラメータが残っていない
 */
int PGMapMk_DelIconParam(MARKER_LIST* pl,u8 idx)
{
	if(pl == NULL){
		return FALSE;
	}
	pl->mark.icon[idx] = MARKER_ICON_NULL;

	//有効なパラメータが残っているかチェック
	if(MarkerDataWk_IsParamEnable(&pl->mark)){
		return TRUE;
	}
	return FALSE;
}

/*
 *	@brief	指定したindex同士のアイコンパラメータをスワップする
 *
 *	@retval	TRUE:成功
 *	@retval FALSE:失敗
 */
int PGMapMk_SwapIconParam(MARKER_LIST* pl,u8 src,u8 dest)
{
	u8	tmp;

	if(pl == NULL){
		return FALSE;
	}
	tmp = pl->mark.icon[src];
	pl->mark.icon[src] = pl->mark.icon[dest];
	pl->mark.icon[dest] = tmp;

	return TRUE;
}

/**
 *	@brief	指定ゾーンのマーカーデータに簡易会話パラメータを追加
 */
int PGMapMk_AddWordParam(MARKER_LIST* pl,u8 idx,PMS_WORD word)
{
	if(pl == NULL){
		return FALSE;
	}
	pl->mark.word[idx] = word;

	return TRUE;
}

/**
 *	@brief	指定ゾーンのマーカーデータから簡易会話パラメータを削除
 *
 *	@retval	TRUE:有効なパラメータが残っている
 *	@retval FALSE:有効なパラメータが残っていない
 */
int PGMapMk_DelWordParam(MARKER_LIST* pl,u8 idx)
{
	if(pl == NULL){
		return FALSE;
	}
	pl->mark.word[idx] = PMS_WORD_NULL;

	//有効なパラメータが残っているかチェック
	if(MarkerDataWk_IsParamEnable(&pl->mark)){
		return TRUE;
	}
	return FALSE;
}

/**
 *	@brief	指定したindex同士のワードデータをスワップする
 */
int PGMapMk_SwapWordParam(MARKER_LIST* pl,u8 src,u8 dest)
{
	PMS_WORD tmp;

	if(pl == NULL){
		return FALSE;
	}
	tmp = pl->mark.word[src];
	pl->mark.word[src] = pl->mark.word[dest];
	pl->mark.word[dest] = tmp;

	return TRUE;
}